
#include <BOpenGL>
#include <BRender>
#include "member_BGeometry.h"
#include "member_BElement.h"

using namespace BWE;

member_BGeometry::member_BGeometry(BGeometry* geometry)
{
	boss = geometry;
}
member_BGeometry::~member_BGeometry()
{

}

void member_BGeometry::drawPiecesLObject(BElement* element, int mode)
{
	if (element_member(element)->dirtyList)
	{
		BPieceArray* pieces = element->pieces();
		BColorArray* cs = colors;
		BVectorArray* vs = vertices;
		BVectorArray* ns = normals;
		BCoordArray* ts = coords[0];
		if (element_member(element)->listName == 0)
		{
			GLuint listName = glGenLists(1);
			element_member(element)->listName = listName;
		}
		GLuint listName = element_member(element)->listName;
		glNewList(listName, GL_COMPILE);
		glBegin(mode);
		for (int i = 0; i < pieces->size(); i++)
		{
			const BPiece& piece = (*pieces)[i];
			if (cs)
			{
				const BColor& color = (*cs)[piece.v()];
				glColor4ubv((GLubyte*)&color);
			}
			if (ts)
			{
				const BCoord& coord = (*ts)[piece.vt()];
				glTexCoord2fv((GLfloat*)&coord);
			}
			if (ns)
			{
				const BVector& normal = (*ns)[piece.vn()];
				BOpenGL::glNormal(normal.x(), normal.y(), normal.z());
			}
			const BVector& vertex = (*vs)[piece.v()];
			BOpenGL::glVector(vertex.x(), vertex.y(), vertex.z());
		}
		glEnd();
		glEndList();
		element_member(element)->dirtyList = false;
	}
	GLuint listName = element_member(element)->listName;
	if (listName > 0)
	{
		glCallList(listName);
	}
}

BSpace member_BGeometry::triangleSpace(const BTriangle& triangle) const
{
	BSpace space(triangle.a());
	space.expand(triangle.b());
	space.expand(triangle.c());
	return space;
}
BSpace member_BGeometry::quadSpace(const BQuad& quad) const
{
	BSpace space(quad.a());
	space.expand(quad.b());
	space.expand(quad.c());
	space.expand(quad.d());
	return space;
}
BSpace member_BGeometry::polygonSpace(const BPolygon& polygon) const
{
	if (polygon.empty())
		return BSpace();
	BSpace s(polygon[0]);
	for (int i = 1; i < polygon.size(); i++)
	{
		s.expand(polygon[i]);
	}
	return s;
}

void member_BGeometry::slotFreshPolyTree()
{
	BSpace treeSpace = polyTree->space();
	const BSpace& space = boss->space();
	if (polyTree && treeSpace.contain(space))
		return;

	polyTree->reset(space);
	for (int i = 0; i < elements.size(); i++)
	{
		const BElement* element = elements[i];
		BPieceArray* pieces = element->pieces();
		if (pieces)
		{
			int size = pieces->size();
			if (element->primitive() == Primitive_Triangles)
			{
				for (int i = 0; i < size; i += 3)
				{
					int ia = (*pieces)[i].v();
					int ib = (*pieces)[i + 1].v();
					int ic = (*pieces)[i + 2].v();
					BTriangle triangle((*vertices)[ia], (*vertices)[ib], (*vertices)[ic]);
					auto item = polyTree->create(triangleSpace(triangle));
					item->triangles.append(triangle);
				}
				continue;
			}
			if (element->primitive() == Primitive_Quads)
			{
				for (int i = 0; i < size; i += 4)
				{
					int ia = (*pieces)[i].v();
					int ib = (*pieces)[i + 1].v();
					int ic = (*pieces)[i + 2].v();
					int id = (*pieces)[i + 3].v();
					BQuad quad((*vertices)[ia], (*vertices)[ib], (*vertices)[ic], (*vertices)[id]);
					auto item = polyTree->create(quadSpace(quad));
					item->quads.append(quad);
				}
				continue;
			}
			continue;
		}
		BIndexArray* indices = element->indices();
		if (indices)
		{
			int size = indices->size();
			if (element->primitive() == Primitive_Triangles)
			{
				for (int i = 0; i < size; i += 3)
				{
					int ia = (*indices)[i];
					int ib = (*indices)[i + 1];
					int ic = (*indices)[i + 2];
					BTriangle triangle((*vertices)[ia], (*vertices)[ib], (*vertices)[ic]);
					auto item = polyTree->create(triangleSpace(triangle));
					item->triangles.append(triangle);
				}
			}
			if (element->primitive() == Primitive_Quads)
			{
				for (int i = 0; i < size; i += 4)
				{
					int ia = (*indices)[i];
					int ib = (*indices)[i + 1];
					int ic = (*indices)[i + 2];
					int id = (*indices)[i + 3];
					BQuad quad((*vertices)[ia], (*vertices)[ib], (*vertices)[ic], (*vertices)[id]);
					auto item = polyTree->create(quadSpace(quad));
					item->quads.append(quad);
				}
			}
			continue;
		}
		int first = element->first();
		int count = element->count();
		if (element->primitive() == Primitive_Triangles)
		{
			for (int c = 0; c < count; c += 3)
			{
				int ia = first + c;
				int ib = ia + 1;
				int ic = ia + 2;
				BTriangle triangle((*vertices)[ia], (*vertices)[ib], (*vertices)[ic]);
				auto item = polyTree->create(triangleSpace(triangle));
				item->triangles.append(triangle);
			}
		}
		if (element->primitive() == Primitive_Quads)
		{
			for (int c = 0; c < count; c += 3)
			{
				int ia = first + c;
				int ib = ia + 1;
				int ic = ib + 1;
				int id = ic + 1;
				BQuad quad((*vertices)[ia], (*vertices)[ib], (*vertices)[ic], (*vertices)[id]);
				auto item = polyTree->create(quadSpace(quad));
				item->quads.append(quad);
			}
		}
		if (element->primitive() == Primitive_Polygon)
		{
			BPolygon polygon;
			polygon.set(vertices->data() + first, count);
			auto item = polyTree->create(polygonSpace(polygon));
			item->polygons.append(polygon);
		}

	}
}

